<!doctype html>

<html>
<head>
  <link rel="shortcut icon" href="static/images/favicon.ico" type="image/x-icon">
  <title>tagiterator.js (Closure Library API Documentation - JavaScript)</title>
  <link rel="stylesheet" href="static/css/base.css">
  <link rel="stylesheet" href="static/css/doc.css">
  <link rel="stylesheet" href="static/css/sidetree.css">
  <link rel="stylesheet" href="static/css/prettify.css">

  <script>
     var _staticFilePath = "static/";
  </script>

  <script src="static/js/doc.js">
  </script>

  <meta charset="utf8">
</head>

<body onload="prettyPrint()">

<div id="header">
  <div class="g-section g-tpl-50-50 g-split">
    <div class="g-unit g-first">
      <a id="logo" href="index.html">Closure Library API Documentation</a>
    </div>

    <div class="g-unit">
      <div class="g-c">
        <strong>Go to class or file:</strong>
        <input type="text" id="ac">
      </div>
    </div>
  </div>
</div>

<div class="clear"></div>

<h2><a href="closure_goog_dom_tagiterator.js.html">tagiterator.js</a></h2>

<pre class="prettyprint lang-js">
<a name="line1"></a>// Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
<a name="line2"></a>// you may not use this file except in compliance with the License.
<a name="line3"></a>// You may obtain a copy of the License at
<a name="line4"></a>//
<a name="line5"></a>//     http://www.apache.org/licenses/LICENSE-2.0
<a name="line6"></a>//
<a name="line7"></a>// Unless required by applicable law or agreed to in writing, software
<a name="line8"></a>// distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
<a name="line9"></a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a name="line10"></a>// See the License for the specific language governing permissions and
<a name="line11"></a>// limitations under the License.
<a name="line12"></a>
<a name="line13"></a>// Copyright 2008 Google Inc. All Rights Reserved.
<a name="line14"></a>
<a name="line15"></a>/**
<a name="line16"></a> * @fileoverview Iterator subclass for DOM tree traversal.
<a name="line17"></a> *
<a name="line18"></a> */
<a name="line19"></a>
<a name="line20"></a>goog.provide(&#39;goog.dom.TagIterator&#39;);
<a name="line21"></a>goog.provide(&#39;goog.dom.TagWalkType&#39;);
<a name="line22"></a>
<a name="line23"></a>goog.require(&#39;goog.dom.NodeType&#39;);
<a name="line24"></a>goog.require(&#39;goog.iter.Iterator&#39;);
<a name="line25"></a>goog.require(&#39;goog.iter.StopIteration&#39;);
<a name="line26"></a>
<a name="line27"></a>/**
<a name="line28"></a> * There are three types of token:
<a name="line29"></a> *  &lt;ol&gt;
<a name="line30"></a> *    &lt;li&gt;{@code START_TAG} - The beginning of a tag.
<a name="line31"></a> *    &lt;li&gt;{@code OTHER} - Any non-element node position.
<a name="line32"></a> *    &lt;li&gt;{@code END_TAG} - The end of a tag.
<a name="line33"></a> *  &lt;/ol&gt;
<a name="line34"></a> * Users of this enumeration can rely on {@code START_TAG + END_TAG = 0} and
<a name="line35"></a> * that {@code OTHER = 0}.
<a name="line36"></a> *
<a name="line37"></a> * @enum {number}
<a name="line38"></a> */
<a name="line39"></a>goog.dom.TagWalkType = {
<a name="line40"></a>  START_TAG: 1,
<a name="line41"></a>  OTHER: 0,
<a name="line42"></a>  END_TAG: -1
<a name="line43"></a>};
<a name="line44"></a>
<a name="line45"></a>
<a name="line46"></a>/**
<a name="line47"></a> * A DOM tree traversal iterator.
<a name="line48"></a> *
<a name="line49"></a> * Starting with the given node, the iterator walks the DOM in order, reporting
<a name="line50"></a> * events for the start and end of Elements, and the presence of text nodes. For
<a name="line51"></a> * example:
<a name="line52"></a> *
<a name="line53"></a> * &lt;pre&gt;
<a name="line54"></a> * &amp;lt;div&amp;gt;1&amp;lt;span&amp;gt;2&amp;lt;/span&amp;gt;3&amp;lt;/div&amp;gt;
<a name="line55"></a> * &lt;/pre&gt;
<a name="line56"></a> *
<a name="line57"></a> * Will return the following nodes:
<a name="line58"></a> *
<a name="line59"></a> * &lt;code&gt;[div, 1, span, 2, span, 3, div]&lt;/code&gt;
<a name="line60"></a> *
<a name="line61"></a> * With the following states:
<a name="line62"></a> *
<a name="line63"></a> * &lt;code&gt;[START, OTHER, START, OTHER, END, OTHER, END]&lt;/code&gt;
<a name="line64"></a> *
<a name="line65"></a> * And the following depths
<a name="line66"></a> *
<a name="line67"></a> * &lt;code&gt;[1, 1, 2, 2, 1, 1, 0]&lt;/code&gt;
<a name="line68"></a> *
<a name="line69"></a> * Imagining &lt;code&gt;|&lt;/code&gt; represents iterator position, the traversal stops at
<a name="line70"></a> * each of the following locations:
<a name="line71"></a> *
<a name="line72"></a> * &lt;pre&gt;
<a name="line73"></a> * &amp;lt;div&amp;gt;|1|&amp;lt;span&amp;gt;|2|&amp;lt;/span&amp;gt;|3|&amp;lt;/div&amp;gt;|
<a name="line74"></a> * &lt;/pre&gt;
<a name="line75"></a> *
<a name="line76"></a> * The iterator can also be used in reverse mode, which will return the nodes
<a name="line77"></a> * and states in the opposite order.  The depths will be slightly different
<a name="line78"></a> * since, like in normal mode, the depth is computed *after* the given node.
<a name="line79"></a> *
<a name="line80"></a> * Lastly, it is possible to create an iterator that is unconstrained, meaning
<a name="line81"></a> * that it will continue iterating until the end of the document instead of
<a name="line82"></a> * until exiting the start node.
<a name="line83"></a> *
<a name="line84"></a> * @param {Node?} opt_node The start node.  If unspecified or null, defaults to
<a name="line85"></a> *     an empty iterator.
<a name="line86"></a> * @param {boolean} opt_reversed Whether to traverse the tree in reverse.
<a name="line87"></a> * @param {boolean} opt_unconstrained Whether the iterator is not constrained to
<a name="line88"></a> *     the starting node and its children.
<a name="line89"></a> * @param {goog.dom.TagWalkType?} opt_tagType The type of the position.
<a name="line90"></a> *     Defaults to the start of the given node for forward iterators, and
<a name="line91"></a> *     the end of the node for reverse iterators.
<a name="line92"></a> * @param {number} opt_depth The starting tree depth.
<a name="line93"></a> * @constructor
<a name="line94"></a> * @extends {goog.iter.Iterator}
<a name="line95"></a> */
<a name="line96"></a>goog.dom.TagIterator = function(opt_node, opt_reversed,
<a name="line97"></a>    opt_unconstrained, opt_tagType, opt_depth) {
<a name="line98"></a>  this.reversed = !!opt_reversed;
<a name="line99"></a>  if (opt_node) {
<a name="line100"></a>    this.setPosition(opt_node, opt_tagType);
<a name="line101"></a>  }
<a name="line102"></a>  this.depth = opt_depth != undefined ? opt_depth : this.tagType || 0;
<a name="line103"></a>  if (this.reversed) {
<a name="line104"></a>    this.depth *= -1;
<a name="line105"></a>  }
<a name="line106"></a>  this.constrained = !opt_unconstrained;
<a name="line107"></a>};
<a name="line108"></a>goog.inherits(goog.dom.TagIterator, goog.iter.Iterator);
<a name="line109"></a>
<a name="line110"></a>
<a name="line111"></a>/**
<a name="line112"></a> * The node this position is located on.
<a name="line113"></a> * @type {Node?}
<a name="line114"></a> */
<a name="line115"></a>goog.dom.TagIterator.prototype.node = null;
<a name="line116"></a>
<a name="line117"></a>
<a name="line118"></a>/**
<a name="line119"></a> * The type of this position.
<a name="line120"></a> * @type {goog.dom.TagWalkType?}
<a name="line121"></a> */
<a name="line122"></a>goog.dom.TagIterator.prototype.tagType = null;
<a name="line123"></a>
<a name="line124"></a>
<a name="line125"></a>/**
<a name="line126"></a> * The tree depth of this position relative to where the iterator started.  The
<a name="line127"></a> * depth is considered to be the tree depth just past the current node, so if an
<a name="line128"></a> * iterator is at position &lt;pre&gt;
<a name="line129"></a> *     &lt;div&gt;|&lt;/div&gt;
<a name="line130"></a> * &lt;/pre&gt;
<a name="line131"></a> * (i.e. the node is the div and the type is START_TAG) it&#39;s depth will be 1.
<a name="line132"></a> * @type {number}
<a name="line133"></a> */
<a name="line134"></a>goog.dom.TagIterator.prototype.depth;
<a name="line135"></a>
<a name="line136"></a>
<a name="line137"></a>/**
<a name="line138"></a> * Whether the node iterator is moving in reverse.
<a name="line139"></a> * @type {boolean}
<a name="line140"></a> */
<a name="line141"></a>goog.dom.TagIterator.prototype.reversed;
<a name="line142"></a>
<a name="line143"></a>
<a name="line144"></a>/**
<a name="line145"></a> * Whether the iterator is constrained to the starting node and its children.
<a name="line146"></a> * @type {boolean}
<a name="line147"></a> */
<a name="line148"></a>goog.dom.TagIterator.prototype.constrained;
<a name="line149"></a>
<a name="line150"></a>
<a name="line151"></a>/**
<a name="line152"></a> * Whether iteration has started.
<a name="line153"></a> * @type {boolean}
<a name="line154"></a> * @private
<a name="line155"></a> */
<a name="line156"></a>goog.dom.TagIterator.prototype.started_ = false;
<a name="line157"></a>
<a name="line158"></a>
<a name="line159"></a>/**
<a name="line160"></a> * Set the position of the iterator.  Overwrite the tree node and the position
<a name="line161"></a> * type which can be one of the {@link goog.dom.TagWalkType} token types.
<a name="line162"></a> * Only overwrites the tree depth when the parameter is specified.
<a name="line163"></a> * @param {Node} node The node to set the position to.
<a name="line164"></a> * @param {goog.dom.TagWalkType?} opt_tagType The type of the position
<a name="line165"></a> *     Defaults to the start of the given node.
<a name="line166"></a> * @param {number} opt_depth The tree depth.
<a name="line167"></a> */
<a name="line168"></a>goog.dom.TagIterator.prototype.setPosition = function(node,
<a name="line169"></a>    opt_tagType, opt_depth) {
<a name="line170"></a>  this.node = node;
<a name="line171"></a>
<a name="line172"></a>  if (node) {
<a name="line173"></a>    if (goog.isNumber(opt_tagType)) {
<a name="line174"></a>      this.tagType = opt_tagType;
<a name="line175"></a>    } else {
<a name="line176"></a>      // Auto-determine the proper type
<a name="line177"></a>      this.tagType = this.node.nodeType != goog.dom.NodeType.ELEMENT ?
<a name="line178"></a>          goog.dom.TagWalkType.OTHER :
<a name="line179"></a>          this.reversed ? goog.dom.TagWalkType.END_TAG :
<a name="line180"></a>          goog.dom.TagWalkType.START_TAG;
<a name="line181"></a>    }
<a name="line182"></a>  }
<a name="line183"></a>
<a name="line184"></a>  if (goog.isNumber(opt_depth)) {
<a name="line185"></a>    this.depth = opt_depth;
<a name="line186"></a>  }
<a name="line187"></a>};
<a name="line188"></a>
<a name="line189"></a>
<a name="line190"></a>/**
<a name="line191"></a> * Replace this iterator&#39;s values with values from another.
<a name="line192"></a> * @param {goog.dom.TagIterator} other The iterator to copy.
<a name="line193"></a> * @protected
<a name="line194"></a> */
<a name="line195"></a>goog.dom.TagIterator.prototype.copyFrom = function(other) {
<a name="line196"></a>  this.node = other.node;
<a name="line197"></a>  this.tagType = other.tagType;
<a name="line198"></a>  this.depth = other.depth;
<a name="line199"></a>  this.reversed = other.reversed;
<a name="line200"></a>  this.constrained = other.constrained;
<a name="line201"></a>};
<a name="line202"></a>
<a name="line203"></a>
<a name="line204"></a>/**
<a name="line205"></a> * @return {goog.dom.TagIterator} A copy of this iterator.
<a name="line206"></a> */
<a name="line207"></a>goog.dom.TagIterator.prototype.clone = function() {
<a name="line208"></a>  return new goog.dom.TagIterator(this.node, this.reversed,
<a name="line209"></a>      !this.constrained, this.tagType, this.depth);
<a name="line210"></a>};
<a name="line211"></a>
<a name="line212"></a>
<a name="line213"></a>/**
<a name="line214"></a> * Skip the current tag.
<a name="line215"></a> */
<a name="line216"></a>goog.dom.TagIterator.prototype.skipTag = function() {
<a name="line217"></a>  var check = this.reversed ? goog.dom.TagWalkType.END_TAG :
<a name="line218"></a>              goog.dom.TagWalkType.START_TAG;
<a name="line219"></a>  if (this.tagType == check) {
<a name="line220"></a>    this.tagType = /** @type {goog.dom.TagWalkType} */ (check * -1);
<a name="line221"></a>    this.depth += this.tagType * (this.reversed ? -1 : 1);
<a name="line222"></a>  }
<a name="line223"></a>};
<a name="line224"></a>
<a name="line225"></a>
<a name="line226"></a>/**
<a name="line227"></a> * Restart the current tag.
<a name="line228"></a> */
<a name="line229"></a>goog.dom.TagIterator.prototype.restartTag = function() {
<a name="line230"></a>  var check = this.reversed ? goog.dom.TagWalkType.START_TAG :
<a name="line231"></a>              goog.dom.TagWalkType.END_TAG;
<a name="line232"></a>  if (this.tagType == check) {
<a name="line233"></a>    this.tagType = /** @type {goog.dom.TagWalkType} */ (check * -1);
<a name="line234"></a>    this.depth += this.tagType * (this.reversed ? -1 : 1);
<a name="line235"></a>  }
<a name="line236"></a>};
<a name="line237"></a>
<a name="line238"></a>
<a name="line239"></a>/**
<a name="line240"></a> * Move to the next position in the DOM tree.
<a name="line241"></a> * @return {Node} Returns the next node, or throws a goog.iter.StopIteration
<a name="line242"></a> *     exception if the end of the iterator&#39;s range has been reached.
<a name="line243"></a> */
<a name="line244"></a>goog.dom.TagIterator.prototype.next = function() {
<a name="line245"></a>  var node;
<a name="line246"></a>
<a name="line247"></a>  if (this.started_) {
<a name="line248"></a>    if (!this.node || this.constrained &amp;&amp; this.depth == 0) {
<a name="line249"></a>      throw goog.iter.StopIteration;
<a name="line250"></a>    }
<a name="line251"></a>    node = this.node;
<a name="line252"></a>
<a name="line253"></a>    var startType = this.reversed ? goog.dom.TagWalkType.END_TAG :
<a name="line254"></a>        goog.dom.TagWalkType.START_TAG;
<a name="line255"></a>
<a name="line256"></a>    if (this.tagType == startType) {
<a name="line257"></a>      // If we have entered the tag, test if there are any children to move to.
<a name="line258"></a>      var child = this.reversed ? node.lastChild : node.firstChild;
<a name="line259"></a>      if (child) {
<a name="line260"></a>        this.setPosition(child);
<a name="line261"></a>      } else {
<a name="line262"></a>        // If not, move on to exiting this tag.
<a name="line263"></a>        this.setPosition(node,
<a name="line264"></a>            /** @type {goog.dom.TagWalkType} */ (startType * -1));
<a name="line265"></a>      }
<a name="line266"></a>    } else {
<a name="line267"></a>      var sibling = this.reversed ? node.previousSibling : node.nextSibling;
<a name="line268"></a>      if (sibling) {
<a name="line269"></a>        // Try to move to the next node.
<a name="line270"></a>        this.setPosition(sibling);
<a name="line271"></a>      } else {
<a name="line272"></a>        // If no such node exists, exit our parent.
<a name="line273"></a>        this.setPosition(node.parentNode,
<a name="line274"></a>            /** @type {goog.dom.TagWalkType} */ (startType * -1));
<a name="line275"></a>      }
<a name="line276"></a>    }
<a name="line277"></a>
<a name="line278"></a>    this.depth += this.tagType * (this.reversed ? -1 : 1);
<a name="line279"></a>  } else {
<a name="line280"></a>    this.started_ = true;
<a name="line281"></a>  }
<a name="line282"></a>
<a name="line283"></a>  // Check the new position for being last, and return it if it&#39;s not.
<a name="line284"></a>  node = this.node;
<a name="line285"></a>  if (!this.node) {
<a name="line286"></a>    throw goog.iter.StopIteration;
<a name="line287"></a>  }
<a name="line288"></a>  return node;
<a name="line289"></a>};
<a name="line290"></a>
<a name="line291"></a>/**
<a name="line292"></a> * @return {boolean} Whether next has ever been called on this iterator.
<a name="line293"></a> * @protected
<a name="line294"></a> */
<a name="line295"></a>goog.dom.TagIterator.prototype.isStarted = function() {
<a name="line296"></a>  return this.started_;
<a name="line297"></a>};
<a name="line298"></a>
<a name="line299"></a>
<a name="line300"></a>/**
<a name="line301"></a> * @return {boolean} Whether this iterator&#39;s position is a start tag position.
<a name="line302"></a> */
<a name="line303"></a>goog.dom.TagIterator.prototype.isStartTag = function() {
<a name="line304"></a>  return this.tagType == goog.dom.TagWalkType.START_TAG;
<a name="line305"></a>};
<a name="line306"></a>
<a name="line307"></a>
<a name="line308"></a>/**
<a name="line309"></a> * @return {boolean} Whether this iterator&#39;s position is an end tag position.
<a name="line310"></a> */
<a name="line311"></a>goog.dom.TagIterator.prototype.isEndTag = function() {
<a name="line312"></a>  return this.tagType == goog.dom.TagWalkType.END_TAG;
<a name="line313"></a>};
<a name="line314"></a>
<a name="line315"></a>
<a name="line316"></a>/**
<a name="line317"></a> * @return {boolean} Whether this iterator&#39;s position is not at an element node.
<a name="line318"></a> */
<a name="line319"></a>goog.dom.TagIterator.prototype.isNonElement = function() {
<a name="line320"></a>  return this.tagType == goog.dom.TagWalkType.OTHER;
<a name="line321"></a>};
<a name="line322"></a>
<a name="line323"></a>
<a name="line324"></a>/**
<a name="line325"></a> * Test if two iterators are at the same position - i.e. if the node and tagType
<a name="line326"></a> * is the same.  This will still return true if the two iterators are moving in
<a name="line327"></a> * opposite directions or have different constraints.
<a name="line328"></a> * @param {goog.dom.TagIterator} other The iterator to compare to.
<a name="line329"></a> * @return {boolean} Whether the two iterators are at the same position.
<a name="line330"></a> */
<a name="line331"></a>goog.dom.TagIterator.prototype.equals = function(other) {
<a name="line332"></a>  // Nodes must be equal, and we must either have reached the end of our tree
<a name="line333"></a>  // or be at the same position.
<a name="line334"></a>  return other.node == this.node &amp;&amp; (!this.node ||
<a name="line335"></a>      other.tagType == this.tagType);
<a name="line336"></a>};
<a name="line337"></a>
<a name="line338"></a>
<a name="line339"></a>/**
<a name="line340"></a> * Replace the current node with the list of nodes. Reset the iterator so that
<a name="line341"></a> * it visits the first of the nodes next.
<a name="line342"></a> * @param {Object} var_args A list of nodes to replace the current node with. If
<a name="line343"></a> *     the first argument is array-like, it will be used, otherwise all the
<a name="line344"></a> *     arguments are assumed to be nodes.
<a name="line345"></a> */
<a name="line346"></a>goog.dom.TagIterator.prototype.splice = function(var_args) {
<a name="line347"></a>  // Reset the iterator so that it iterates over the first replacement node in
<a name="line348"></a>  // the arguments on the next iteration.
<a name="line349"></a>  var node = this.node;
<a name="line350"></a>  this.restartTag();
<a name="line351"></a>  this.reversed = !this.reversed;
<a name="line352"></a>  goog.dom.TagIterator.prototype.next.call(this);
<a name="line353"></a>  this.reversed = !this.reversed;
<a name="line354"></a>
<a name="line355"></a>  // Replace the node with the arguments.
<a name="line356"></a>  var arr = goog.isArrayLike(arguments[0]) ? arguments[0] : arguments;
<a name="line357"></a>  for (var i = arr.length - 1; i &gt;= 0; i--) {
<a name="line358"></a>    goog.dom.insertSiblingAfter(arr[i], node);
<a name="line359"></a>  }
<a name="line360"></a>  goog.dom.removeNode(node);
<a name="line361"></a>};
</pre>


</body>
</html>
